<style scoped>
.category{width: 150px;height: 100%;border-right: solid 1px var(--el-menu-border-color);overflow-y: auto;}
.category::-webkit-scrollbar{display: none;}
.category .el-menu{border: none;}

.file_row{width: 150px;padding: 05px;position: relative;flex-direction: column;background: var(--bg);margin: 05px;text-align: center;}
.file_row .img{width: 140px;height: 140px;background-image: url("@/assets/img/show_img_bg.png");}
.file_row .file_type{position: absolute;left: 21px;top: 23px;width: 52px;text-align: center;color: #ffffff;font-size: 18px;text-shadow: 1px 1px 3px rgba(255, 255, 255, 0.8), -1px -1px 3px rgba(255, 255, 255, 0.8);transform: rotate(1deg);}
.file_row .name{line-height: 1.5em;}
.file_row .el-checkbox{position: absolute;left: 10px;top: 0;transform: scale(1.5);}
.file_row i.ico-wechat{position: absolute;top: 0;right: 0;font-size: 25px;line-height: 1;color: var(--sm_bg);display: none;}
.file_row i.ico-wechat.on{color: var(--el-color-primary);display: block;}

.video_frame-outer>*{width: 100%;}
.video_frame-outer>.imgs{align-items: flex-start;align-content: flex-start;flex-wrap: wrap;overflow-y: scroll;}
.video_frame-outer>.imgs>img{display: block;width: 200px;margin: 5px;}
.video_frame-outer>.imgs>img:hover{box-shadow: 0 0 5px 3px var(--el-color-primary-light-3);}
.video_frame-outer>.imgs>img.on{box-shadow: 0 0 5px 3px var(--el-color-primary);}

.error_message{color: var(--el-color-error);}

</style>
<template>
  <input type="file" style="display: none" ref="input_file" accept="image/jpeg,image/png,image/gif,video/mp4,audio/mp3" multiple="multiple" @change="upload">
  <div class="flex" style="height: 100%;">
    <!--类目列表-->
    <div class="category">
      <menu_slot :config="category" :default-active="file_category_id" @click:li="click_cat">
        <template #default="{row}">
          <p v-if="row.id==0" class="text-ellipsis" :title="row.content">{{ row.content }}</p>
          <el-popover v-else trigger="hover" placement="right" :width="150" :show-after="500">
            <template #reference><p class="text-ellipsis" :title="row.content">{{ row.content }}</p></template>
            <div class="flex" v-if="row.id>0">
              <el-button v-if="can_cat_edit" @click.stop="file_category_edit(row.id)" circle type="primary"><i ico="s94" class="ico-edit"></i></el-button>
              <el-button v-if="can_cat_delete" @click.stop="file_category_delete(row.id)" circle type="danger"><i ico="s94" class="ico-delete"></i></el-button>
            </div>
          </el-popover>
        </template>
      </menu_slot>
    </div>
    <!--列表-->
    <list_url ref="list_url" is_scroll="1" :config="config" class="max">
      <template #list_row="{row,index,select_toggle,is_select}">
        <div class="file_row" :title="row.name">
          <el-image class="img" fit="contain" :src="head_img(row)" referrerpolicy="no-referrer"
                    @click="~['mp3','mp4'].indexOf(row.type) && show_file(row.url)"
                    v-bind="preview_list_index(row, index)" :preview-teleported="true" :infinite="false"
          ></el-image>
          <p class="file_type" v-show="!row.head_img && !~img_types.indexOf(row.type)">{{ row.type }}</p>
          <div class="name text-ellipsis">{{row.name}}</div>
          <el-checkbox :model-value="is_select" @click="select_toggle(row)"></el-checkbox>
          <i ico="s94" class="ico-wechat" :class="{on:row.media_id}" title="此素材在微信素材中也存在"></i>
        </div>
      </template>
    </list_url>
    <!--变更分类表单-->
    <el-dialog v-model="show_edit" title="移动至" width="650px">
      <forms :config="edit_config" @submit:forms="edit_category"></forms>
    </el-dialog>
  </div>
  <!--上传进度-->
  <el-dialog v-model="uploading.status" :modal="false" width="80%" style="margin: 5vh auto;" :close-delay="100" :show-close="uploading.can_close" :close-on-click-modal="false" :close-on-press-escape="false">
    <ul style="width: 100%;overflow: auto;">
      <li v-for="row in uploading.list">
        <div class="flex" style="height: 45px;">
          <p class="text-ellipsis" style="width: 200px;max-width: 25%;">{{row.name}}</p>
          <el-progress class="max" style="padding: 0 05px;" :status="['warning','success','exception'][row.step]" :percentage="row.percentage" :text-inside="true" :stroke-width="24"></el-progress>
          <p style="width: 6em;">{{row.tips}}</p>
        </div>
        <p v-if="row.error" class="error_message">{{row.error}}</p>
      </li>
    </ul>
  </el-dialog>
  <!--设定封面-->
  <el-dialog v-model="video_frame.show" width="80%" :draggable="true" style="margin: auto;margin-top: 5vh;" :destroy-on-close="true">
    <div class="flex video_frame-outer" style="flex-direction: column;height: 80vh;">
      <div class="imgs flex max">
        <img v-for="(v,i) in video_frame.imgs" :src="v.url" @click="video_frame.index=i" :class="{on:video_frame.index==i}">
      </div>
      <div style="text-align: right;">
        <el-button @click="set_head_img" type="primary">确定</el-button>
      </div>
    </div>
  </el-dialog>

</template>
<script>
import Spark_md5 from 'spark-md5';
import VideoFrame from '@/assets/VideoFrame.es6.js';
import root_img from '@/assets/img/file_type/__root.png';
import {_config, _href, decode_config} from "@/js/s94_tool.js";
import {media_duration} from "@/js/dom_tool.js";
import {confirm, iframe, in_right_admin, show_file} from "@/js/tool.js";
import s94Mjs from "s94-js";
import {ajax, file_upload} from "@/js/api_tool.js";

export default {
  props: ['__iframe'],
  data(){
    let app = this, btns = {}, is_del = this.$get('is_del');

    btns['设置封面'] = function(){
      let list = app.$refs['list_url'].selected;
      if (list.length !== 1) return app.$message.error('只能选择一个');
      let row = list[0];
      if (row.type !== 'mp4') return app.$message.error('请选择视频素材');
      let vf = new VideoFrame(row.url, {width:640, type:'image/jpeg', quality:0.8});
      app.video_frame.init(row);
      for (let i = 0; i < 11; i++) {
        vf.capture(i).then(function (v){
          app.video_frame.imgs.push(v)
        })
      }
    }

    if(in_right_admin('File/sync')) btns['同步'] = function(){
      if (app.uploading.status) return app.$message('请稍后再试！');
      app.uploading.status = true;
      app.uploading.list.push({percentage:0, name:'素材同步', tips:'', step:1})
      function loop(){
        ajax('/admin/file/sync?limit=20', function (res){
          if (res.data.count > res.data.num) {
            app.uploading.list[0].percentage = Math.floor(10000*(res.data.num/res.data.count))/100;
            setTimeout(loop);
          }else {
            app.uploading.list[0].percentage = 100;
            setTimeout(function (){
              app.uploading.status = false;
              app.uploading.list = [];
            }, 30);
            app.$refs.list_url.list();
          }
        })
      }
      loop();
    }
    if(in_right_admin('File/upload_to_wechat')) btns['上传至微信'] = function (){
      let list = app.$refs['list_url'].selected;
      let ids = [];
      s94Mjs.each(list, function (v){
        if (!v.media_id) ids.push(v.id);
      })
      let count=ids.length, num=0;
      if (!count) return app.$message.error('请选择至少一个在微信中不存在的素材');
      s94Mjs.each(ids, {
        limit: 1,
        each(id){
          return new Promise((resolve)=>{
            ajax({url:'/admin/file/upload_to_wechat?id='+id, loading: true}, function (res){
              num++;
              app.$message('上传进度：'+num+'/'+count);
              resolve();
              return false;
            },function (){resolve();})
          })
        },
        over() {
          app.$refs['list_url'].list();
          return app.$message.success('上传完成');
        }
      })
    }
    if(in_right_admin('File/edit_category')) btns['移动至'] = function (){
      let ids = app.$refs['list_url'].selected_ids;
      if (!ids.length) return app.$message.error('请选需要移动的文件素材');
      app.show_edit = true;
      app.edit_config.ids.value = ids.join(',');
    }
    if(in_right_admin('FileCategory/add')) btns['添加分类'] = function(){
      iframe('file_category/edit');
    }
    if(in_right_admin('File/upload')) btns['上传文件_primary'] = function(){ app.$refs['input_file'].click() }
    if(in_right_admin('File/delete')) btns['彻底删除'] = function(){ app.$refs['list_url'].delete() }
    let type_map = [
      {content:'图片',value:'jpg,jpeg,png,gif,webp'},
      {content:'音频',value:'mp3'},
      {content:'视频',value:'mp4'},
    ];
    var need_type = this.$get('type','');
    let forms_config = {
      name: {label:'文件名',name:'where[name|url][like]',type:'text_one',value:''},
      type: {label:'类型',name:'where[type][in]',type:(need_type?'hidden':'select_one'),config:type_map,value:need_type},
    };

    return {
      img_types: ['jpg','jpeg','png','gif','webp'],
      file_category_id: '0',
      uploading: { status: false, list: [], can_close:false },
      category: [],
      can_cat_edit: in_right_admin('FileCategory/edit'),
      can_cat_delete: in_right_admin('FileCategory/delete'),
      config: {
        api: '/admin/file/'+(is_del?'recycle':'list'),
        title: "素材列表"+(is_del?'(已删除)':''),
        btns: btns,
        forms_config: forms_config,
        list_cols: false,
        resdata: function(list){
          return list;
        },
        limit: 50,
        p: this.$get('p', 1),
        order: 'create_time desc',
      },
      show_edit: false,
      edit_config: {
        ids: {label:'ids',name:'ids',type:'hidden',tips:''},
        file_category_id: {label:'选择分类',name:'file_category_id',type:'select_one',config:[],tips:''},
      },
      video_frame: {
        show:false,
        index:-1,
        imgs:[],
        row:{},
        init(row){
          this.show=!!row;
          this.index=-1;
          this.imgs=[];
          this.row=row || {}
        }
      },
    }
  },
  methods: {
    to_edit(row){
      let can_edit = in_right_admin('File/add') && ~[0,row.tenant_id].indexOf(_config('this_tenant.id'))
      let param = {
        id: row.id,
      }
      if (!can_edit) param['is_info'] = 1;
      iframe('file/edit?'+s94Mjs.param_encode(param))
    },
    head_img(row){
      let head_img = row.head_img;
      if (!head_img){
        if (~this.img_types.indexOf(row.type)){
          head_img = row.url+(row.disk === 'aliyun' ? '?x-oss-process=image/resize,w_200/quality,q_80' : '');
        }else {
          return root_img;
        }
      }
      return _href(head_img);
    },
    show_file: show_file,
    click_cat(row){
      if (row.children || this.file_category_id == row.value) return;
      this.file_category_id = row.value;
      this.config.api = '/admin/file/list'+(row.value>0 ? '?where[file_category_id][eq]='+row.value : '');
      this.$refs['list_url'].search();
    },
    file_md5(file, i){ //得到文件MD5，next传入md5字符串
      let app = this;
      var md5 = new Spark_md5();
      let unit_size = 10*1024*1024;
      let fr = new FileReader();

      let over = false, start = 0;
      function loop(){
        let end = 0;
        if(start + unit_size > file.size){
          end = file.size;
          over = true;
        }else {
          end = start + unit_size;
        }
        let data = file.slice(start, end);
        fr.readAsBinaryString(data);
        start = end;
      }
      return new Promise(function (next){
        fr.onload = function (e){
          md5.appendBinary(this.result);
          app.uploading.list[i].percentage = Math.floor(start*100/file.size);
          if (over){
            next(md5.end());
          }else {
            loop();
          }
        }
        loop();
      })
    },
    upload(e){
      let app = this;
      let upload_extend_list = [];
      if (app.uploading.status) return app.$message.error('上传中，请稍后！');
      let dom = e.target;
      app.uploading.can_close = false;
      app.uploading.status = true;
      app.uploading.list = [];
      s94Mjs.each(dom.files, function (f){
        app.uploading.list.push({name:f.name, percentage:0, tips:'', step:0})
      })
      s94Mjs.each(dom.files, {
        each(f, i){
          let is_video = /^video\//.test(f.type);
          let is_audio = /^audio\//.test(f.type);
          return new Promise((next_file)=>{
            file_upload(f, ({type, progress, message})=>{
              app.uploading.list[i].step = ['md5','upload','upload_error'].indexOf(type);
              app.uploading.list[i].percentage = Math.floor((i+progress)*100);
              app.uploading.list[i].tips = message;
            }, {file_category_id:app.file_category_id}).then((file_data)=>{
              // app.uploading.list[i].tips = '上传成功';
              if (is_video || is_audio){
                upload_extend_list.push({file: f, file_data, is_video});
              }
              next_file();
            }).catch((err)=>{
              app.uploading.list[i].step = 2;
              app.uploading.list[i].error = err.message;
              next_file();
            })
          })
        },
        over(){
          s94Mjs.each(upload_extend_list, {
            each({file, file_data, is_video}){
              if (file_data.head_img && file_data.duration>0) return true;
              return new Promise(function (resolve){
                let formData = new FormData();
                formData.append('id', file_data.id);
                let need = 0;
                function set_data_after(){
                  if (--need > 0) return;
                  ajax({url:'/home/api/file_upload_extend', method:'POST', data: formData}, resolve)
                }
                if (file_data.duration <= 0){
                  need++;
                  media_duration(file, is_video).then((duration)=>{
                    formData.append('duration', duration);
                    set_data_after();
                  })
                }
                if (is_video && !file_data.head_img){
                  need++;
                  let vf = new VideoFrame(file, {width:640});
                  vf.capture(1).then(v=>{
                    let head_img = new File([v.blob], file.name.replace(/\..+?$/,'_封面_1s.jpg'));
                    formData.append('head_img', head_img);
                    set_data_after();
                  })
                }
              })
            },
            over(){
              dom.value = '';
              app.$refs['list_url'].list();
              app.uploading.can_close = true;
              let has_error = app.uploading.list.some(row=>{ return !!row.error; });
              if (!has_error){
                setTimeout(()=>{
                  app.uploading.list = [];
                  app.uploading.status = false;
                },500);
              }
            }
          })
        }
      })
    },
    get_category(){
      let app = this;
      ajax({url:'/admin/file_category/list',cache:true}, function (res){
        let category_map = decode_config(res.data.list, {content_key:'name',value_key:'id',index_key:'id',parent_key:'parent_id'});
        category_map.unshift({content:'全部', value:'0', id:0, name:'全部'})
        app.category = category_map;
        app.edit_config.file_category_id.config = category_map;
        return false;
      })
    },
    edit_category(formData){
      ajax({url:'/admin/file/edit_category', method:'POST', data: formData}, (res)=>{
        this.show_edit = false;
        if (this.file_category_id != 0) this.$refs.list_url.list();
      })
    },
    file_category_edit(id){
      iframe('/file_category/edit?id='+id)
    },
    file_category_delete(id){
      confirm.error('是否确定彻底删除选中的素材分类').then(()=>{
        ajax({url:'/admin/file_category/delete?ids='+id, loading:true}, (res)=>{
          this.get_category();
        })
      }).catch(()=>{})
    },
    set_head_img() {
      if (!this.video_frame.imgs[this.video_frame.index]) return this.$message('请选择图片');
      let blob = this.video_frame.imgs[this.video_frame.index]['blob'];
      let row = this.video_frame.row;
      let formData = new FormData();
      let head_img = new File([blob], row.name.replace(/\..+?$/,'_封面_'+(this.video_frame.index+1)+'s.jpg'));
      formData.append('id', row.id);
      formData.append('head_img', head_img);
      ajax({url:'/home/api/file_upload_extend', method:'POST', data: formData}, (res)=>{
        this.video_frame.init();
        this.$refs.list_url.list();
      })
    },
    preview_list_index(row, index){
      let res = {
        'preview-src-list': [],
        'initial-index': 0
      }
      if (!~this.img_types.indexOf(row.type)) return res;
      let list = this.$refs.list_url.list_data || [];
      Object.values(list).forEach((row, i)=>{
        if (!~this.img_types.indexOf(row.type)) return;
        if (i == index) res['initial-index'] = res['preview-src-list'].length;
        res['preview-src-list'].push(row.url);
      })
      return res;
    }
  },
  computed: {
  },
  mounted() {
    let app = this;
    if (!this.__iframe) window['app'] = this;

    this.get_category();
  }
}
</script>
